package com.javalaoniu.tool.http.client;

import com.javalaoniu.tool.http.constant.MimeTypeEnum;
import com.javalaoniu.tool.http.constant.RequestMethod;
import com.javalaoniu.tool.http.entity.HttpDataEntity;
import com.javalaoniu.tool.http.exception.HttpClientUtilException;
import com.javalaoniu.tool.http.manage.LocalHttpConnectionManager;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author: xianninig
 * @date: 2018/8/29 16:35
 */
public class HttpClientUtil {
    private static final Logger LOG = LoggerFactory.getLogger(HttpClientUtil.class);


    /**
     * 请求超时时间，httpclient使用连接池来管理连接，这个时间就是从连接池获取连接的超时时间，单位毫秒
     *
     */
    private static final Integer DEFAULT_REQUEST_TIMEOUT = 3000;

    /**
     * 套接字超时时间，数据传输过程中数据包之间间隔的最大时间，单位毫秒
     */
    private static final Integer DEFAULT_SOCKET_TIMEOUT = 3000;

    /**
     * 默认连接超时时间，连接建立时间，三次握手完成时间，单位毫秒
     */
    private static final Integer DEFAULT_CONNECTION_TIMEOUT = 3000;

    public static String sendHttp(RequestMethod method, String url, HttpDataEntity httpDataEntity, MimeTypeEnum
            contentType, int timeOut) {
        String response = null;
        if (method == RequestMethod.GET) {
            response = doGet(url, httpDataEntity, contentType, timeOut);
        } else if (method == RequestMethod.POST) {
            response = doPost(url, httpDataEntity, contentType, timeOut);
        }
        return response;
    }

    /**
     * @param doGetUrl       请求的URL
     * @param httpDataEntity 请求实体
     * @param contentType    contentType
     * @param timeOut        超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doGet(String doGetUrl, HttpDataEntity httpDataEntity, MimeTypeEnum contentType, int timeOut)
            throws HttpClientUtilException {

        /**
         * 创建请求的基本的对象
         */
        CloseableHttpClient httpClient = LocalHttpConnectionManager.getHttpClient();
        Map<String, Object> requestMap = httpDataEntity.getMap();

        //拼接get参数
        if (null != requestMap && requestMap.size() > 0) {
            Set<String> keySet = requestMap.keySet();
            doGetUrl += "?";
            for (String key : keySet) {
                Object value = requestMap.get(key);
                doGetUrl += key + "=" + value + "&";
            }
        }

        RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT)
                .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setCookieSpec(CookieSpecs.STANDARD);
        RequestConfig requestConfig;
        if (timeOut <= 0) {
            requestConfig = builder.setConnectionRequestTimeout(DEFAULT_REQUEST_TIMEOUT).build();
        } else {
            requestConfig = builder.setConnectionRequestTimeout(timeOut).build();
        }
        HttpGet httpGet = new HttpGet(doGetUrl);
        httpGet.setConfig(requestConfig);
        httpGet.addHeader("Accept-Charset", "UTF-8");
        httpGet.setHeader(
                "User-Agent",
                "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118" +
                        " Safari/537.36");
        if (null == contentType) {
            httpGet.addHeader("Content-Type", MimeTypeEnum.APPLICATION_FORM_URLENCODED.getMimeType());
        } else {
            httpGet.addHeader("Content-Type", contentType.getMimeType());
        }

        CloseableHttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 获取服务端返回的数据,并返回
                return EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            LOG.error("Failed in requesting "+doGetUrl+" data. error {}:{}", e.getClass(), e.getMessage());

        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    LOG.error("close http stream failed, error:{}", e.getMessage());
                }
            }
        }
        return null;
    }


    /**
     * @param doGetUrl 请求的URL
     * @return
     * @throws HttpClientUtilException
     */
    public static String doGet(String doGetUrl) throws HttpClientUtilException {
        return doGet(doGetUrl, HttpDataEntity.createHttpDataEntity(), MimeTypeEnum.APPLICATION_FORM_URLENCODED,
                DEFAULT_REQUEST_TIMEOUT);
    }

    /**
     * @param doGetUrl 请求的URL
     * @param timeOut  超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doGet(String doGetUrl, int timeOut) throws HttpClientUtilException {
        return doGet(doGetUrl, HttpDataEntity.createHttpDataEntity(), MimeTypeEnum.APPLICATION_FORM_URLENCODED,
                timeOut);
    }

    /**
     * @param doGetUrl       请求的URL
     * @param httpDataEntity 请求实体
     * @return
     * @throws HttpClientUtilException
     */
    public static String doGet(String doGetUrl, HttpDataEntity httpDataEntity) throws HttpClientUtilException {
        return doGet(doGetUrl, httpDataEntity, MimeTypeEnum.APPLICATION_FORM_URLENCODED, DEFAULT_REQUEST_TIMEOUT);
    }

    /**
     * @param doGetUrl       请求的URL
     * @param httpDataEntity 请求实体
     * @param timeOut        超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doGet(String doGetUrl, HttpDataEntity httpDataEntity, int timeOut) throws
            HttpClientUtilException {
        return doGet(doGetUrl, httpDataEntity, MimeTypeEnum.APPLICATION_FORM_URLENCODED, timeOut);
    }

    /**
     * @param doPostUrl      请求的URL
     * @param httpDataEntity 请求实体
     * @param contentType    contentType
     * @param timeOut        超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, HttpDataEntity httpDataEntity, MimeTypeEnum contentType, int
            timeOut) throws HttpClientUtilException {
        /**
         * 创建 请求的对象
         */
        CloseableHttpClient httpClient = LocalHttpConnectionManager.getHttpClient();
        RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT)
                .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setCookieSpec(CookieSpecs.STANDARD);
        RequestConfig requestConfig = null;
        if (timeOut <= 0) {
            builder.setConnectionRequestTimeout(DEFAULT_REQUEST_TIMEOUT).build();
        } else {
            builder.setConnectionRequestTimeout(timeOut).build();
        }

        /**
         * 设置请求的post
         */
        HttpPost httpPost = new HttpPost(doPostUrl);
        httpPost.setConfig(requestConfig);

        /**
         * 请求的参数
         */
        List<NameValuePair> params = new ArrayList<NameValuePair>(5);
        Map<String, Object> map = httpDataEntity.getMap();
        if (null != map && map.size() > 0) {
            Set<String> keys = map.keySet();
            for (String key : keys) {
                Object value = map.get(key);
                params.add(new BasicNameValuePair(key, String.valueOf(value)));
            }
        }

        if (params.size() > 0) {
            try {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
                /**
                 * 设置请求的数据
                 */
                httpPost.setEntity(entity);
            } catch (UnsupportedEncodingException e) {
                LOG.error("Failed in set "+doPostUrl+" params. {}", e.getMessage());
            }

        }

        httpPost.setHeader(
                "User-Agent",
                "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118" +
                        " Safari/537.36");
        if (null != contentType && !"".equals(contentType)) {
            httpPost.addHeader("Content-Type", contentType.getMimeType());
        } else {
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
        }
        httpPost.addHeader("Connection", "Keep-Alive");

        CloseableHttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(httpPost);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                // 获取服务端返回的数据,并返回
                return EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            LOG.error("Failed in requesting "+doPostUrl+" data. error {}:{}", e.getClass(), e.getMessage());
        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    LOG.error("close http stream failed, error:{}", e.getMessage());
                }
            }
        }
        return null;
    }

    /**
     * @param doPostUrl 请求的URL
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl) throws HttpClientUtilException {
        return doPost(doPostUrl, HttpDataEntity.createHttpDataEntity(), MimeTypeEnum.APPLICATION_FORM_URLENCODED,
                DEFAULT_REQUEST_TIMEOUT);
    }

    /**
     * @param doPostUrl 请求的URL
     * @param timeOut   超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, int timeOut) throws HttpClientUtilException {
        return doPost(doPostUrl, HttpDataEntity.createHttpDataEntity(), MimeTypeEnum.APPLICATION_FORM_URLENCODED,
                timeOut);
    }

    /**
     * @param doPostUrl   请求的URL
     * @param contentType contentType
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, MimeTypeEnum contentType) throws HttpClientUtilException {
        return doPost(doPostUrl, HttpDataEntity.createHttpDataEntity(), contentType, DEFAULT_REQUEST_TIMEOUT);
    }

    /**
     * @param doPostUrl   请求的URL
     * @param contentType contentType
     * @param timeOut     超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, MimeTypeEnum contentType, int timeOut) throws
            HttpClientUtilException {
        return doPost(doPostUrl, HttpDataEntity.createHttpDataEntity(), contentType, timeOut);
    }


    /**
     * @param doPostUrl      请求的URL
     * @param httpDataEntity 请求实体
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, HttpDataEntity httpDataEntity) throws HttpClientUtilException {
        return doPost(doPostUrl, httpDataEntity, MimeTypeEnum.APPLICATION_FORM_URLENCODED, DEFAULT_REQUEST_TIMEOUT);
    }

    /**
     * @param doPostUrl      请求的URL
     * @param httpDataEntity 请求实体
     * @param timeOut        超时时间
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, HttpDataEntity httpDataEntity, int timeOut) throws
            HttpClientUtilException {
        return doPost(doPostUrl, httpDataEntity, MimeTypeEnum.APPLICATION_FORM_URLENCODED, timeOut);
    }

    /**
     * @param doPostUrl      请求的URL
     * @param httpDataEntity 请求实体
     * @param contentType    contentType
     * @return
     * @throws HttpClientUtilException
     */
    public static String doPost(String doPostUrl, HttpDataEntity httpDataEntity, MimeTypeEnum contentType) throws
            HttpClientUtilException {
        return doPost(doPostUrl, httpDataEntity, contentType, DEFAULT_REQUEST_TIMEOUT);
    }

}
